package com.zhuojy.equity.mall.admin.web.config;

import com.zhuojy.equity.mall.admin.web.security.component.DynamicSecurityFilter;
import com.zhuojy.equity.mall.admin.web.security.component.JwtAuthenticationTokenFilter;
import com.zhuojy.equity.mall.admin.web.security.component.RestAuthenticationEntryPoint;
import com.zhuojy.equity.mall.admin.web.security.component.RestfulAccessDeniedHandler;
import com.zhuojy.equity.mall.admin.web.security.config.IgnoreUrlsConfig;
import lombok.RequiredArgsConstructor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 * SpringSecurity相关配置，仅用于配置SecurityFilterChain
 */
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

	private final IgnoreUrlsConfig ignoreUrlsConfig;

	private final RestfulAccessDeniedHandler restfulAccessDeniedHandler;

	private final RestAuthenticationEntryPoint restAuthenticationEntryPoint;

	private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

	private final DynamicSecurityFilter dynamicSecurityFilter;

	@Bean
	SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
		ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
		//不需要保护的资源路径允许访问
		for (String url : ignoreUrlsConfig.getUrls()) {
			registry.antMatchers(url).permitAll();
		}
		//允许跨域请求的OPTIONS请求
		registry.antMatchers(HttpMethod.OPTIONS).permitAll();
		// 任何请求需要身份认证
		registry.and().authorizeRequests().anyRequest().authenticated()
				// 关闭跨站请求防护及不使用session
				.and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
				// 自定义权限拒绝处理类
				.and().exceptionHandling().accessDeniedHandler(restfulAccessDeniedHandler)
				.authenticationEntryPoint(restAuthenticationEntryPoint)
				// 自定义权限拦截器JWT过滤器
				.and().addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
		// 添加动态权限校验过滤器
		registry.and().addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
		return httpSecurity.build();
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
}
